﻿using System;
using System.Text;

namespace cc.hanzs.json {

    public class JSONObject {

        private JSONObject() {
        }

        public Object parent = null;
        private String path_s = null;
        private System.Collections.Hashtable ji集合 = null;
        private static JSONObject i_JSON = new JSONObject();

        public void set(JSONTokener x){
            this.clear();
            char c;
            String key;
            Object value;

            if (x.nextClean() != '{') {
                throw new JSONException("JSON文本必需以'{'开始！");
            }
            for (;;) {
                c = x.nextClean();
                switch (c) {
                    case (char)0:
                        throw new JSONException("JSON文本必需以'}'结束！");
                    case '}':
                        return;
                    default:
                        x.back();
                        key = x.nextValue(null).ToString();
                        break;
                }

                /*
                 * The key is followed by ':'. We will also tolerate '=' or '=>'.
                 */
                c = x.nextClean();
                if (c == '=') {
                    if (x.next() != '>') {
                        x.back();
                    }
                } else if (c != ':') {
                    throw new JSONException("Expected a ':' after a key");
                }
                value = x.nextValue(this);
                if (value != null) {
                    ji集合.Add(key, value);
                }

                /*
                 * Pairs are separated by ','. We will also tolerate ';'.
                 */
                switch (x.nextClean()) {
                    case ';':
                    case ',':
                        if (x.nextClean() == '}') {
                            return;
                        }
                        x.back();
                        break;
                    case '}':
                        return;
                    default:
                        throw new JSONException("Expected a ',' or '}'");
                }
            }
        }

        public void setPath(Object root) {
            foreach (System.Collections.DictionaryEntry objDE in ji集合)
            {
                if (objDE.Value is JSONPath)
                {
                    ((JSONPath)objDE.Value).root = root;
                    ((JSONPath)objDE.Value).i当前 = this;
                }
                else if (objDE.Value is JSONObject)
                {
                    ((cc.hanzs.json.JSONObject)objDE.Value).setPath(root);
                }
                else if (objDE.Value is JSONArray)
                {
                    ((cc.hanzs.json.JSONArray)objDE.Value).setPath(root);
                }                
            }
        }

        /**
         * @param ci_s 待解析文本
         * @return 解析生成的org.hzs.JSONObject
         */
        public JSONObject set(String ci_s){
            if (ci_s == null) {
                return null;
            }
            set(JSONTokener.d副本(ci_s));
            setPath(this);
            return this;
        }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public static bool testValidity(Object o) {
            if (o == null) {
                return false;
            }
            if (o is Double) {
                if ( Double.IsInfinity((Double) o) || Double.IsNaN((Double) o)) {
    //                ci_error.g添加错误信息("JSON不允许非有限数");
    //                throw ci_error;
                    return false;
                }
            }
            return true;
        }

        /**
         * @param key 待加入的键，为空时不加入
         * @param value 待加入的值，为空时删除对应的键
         * @return 加入的值
         */
        public cc.hanzs.json.JSONObject put(String key, Object value) {
            if (key == null) {
                return this;
            }

            ji集合.Remove(key);
            if (value != null && testValidity(value)){
                ji集合.Add(key, value);
            }
            return this;
        }


        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /**
         * @since
         */
        private static String quote(String str) {
            if (str == null || str.Length == 0) {
                return "\"\"";
            }

            char b;
            char c = (char)0;
            int i;
            int len = str.Length;
            StringBuilder sb = new StringBuilder(len + 4);
            String t;

            sb.Append('"');
            for (i = 0; i < len; i += 1) {
                b = c;
                c = str.ToCharArray(i, 1)[0];
                switch (c) {
                    case '\\':
                    case '"':
                        sb.Append('\\');
                        sb.Append(c);
                        break;
                    case '/':
                        if (b == '<') {
                            sb.Append('\\');
                        }
                        sb.Append(c);
                        break;
                    case '\b':
                        sb.Append("\\b");
                        break;
                    case '\t':
                        sb.Append("\\t");
                        break;
                    case '\n':
                        sb.Append("\\n");
                        break;
                    case '\f':
                        sb.Append("\\f");
                        break;
                    case '\r':
                        sb.Append("\\r");
                        break;
                    default:
                        if (c < ' ') {
                            t = "000" + System.Convert.ToString(c, 16);
                            sb.Append("\\u").Append(t.Substring(t.Length - 4));
                        } else {
                            sb.Append(c);
                        }
                        break;
                }
            }
            sb.Append('"');
            return sb.ToString();
        }


        /**
         *
         * @param key 为空时抛出错误
         * @return 返回取得的值；若key不存在，则返回空值。
         */
        public Object get(Object key) {
            if (key == null) {
                return null;
            }
            foreach (System.Collections.DictionaryEntry objDE in ji集合)
            {
                if (objDE.Key.Equals(key)) {
                    return objDE.Value;
                }
            }
            return null;
        }

        /**
         *
         * @param key 为空时抛出错误
         * @return 返回取得的值；若key不存在，则返回空值。
         */
        public Boolean getBoolean(Object key) {
            Object o = get(key);
            if (o == null){
                return false;
            }
            if (false.Equals(o) || (o is String && ((String) o).ToLower().Equals("false"))) {
                return false;
            } else if (true.Equals(o) || (o is String && ((String) o).ToLower().Equals("true"))) {
                return true;
            }
            return false;
        }


        /**
         *
         * @param key 为空时抛出错误
         * @return 返回取得的值；若key不存在，则返回空值。
         */
        public Double getDouble(Object key) {
            Object o = get(key);
            if (o == null) {
                return 0;
            }
            if (o is int || o is Int16 || o is Int64 || o is double) {
                return ((double) o);
            }
            return System.Convert.ToDouble(o);
        }


        /**
         *
         * @param key 为空时抛出错误
         * @return 返回取得的值；若key不存在，则返回空值。
         */
        public int getInt(Object key) {
            Object o = get(key);
            if (o == null) {
                return 0;
            }
            if (o is Int32 || o is Int16 || o is Int64 || o is double) {
                return ((int) o);
            }
            return System.Convert.ToInt32(o);
        }

        /**
         *
         * @param key 为空时抛出错误
         * @return 返回取得的值；若key不存在，则返回空值。
         */
        public JSONArray getJSONArray(Object key) {
            Object o = get(key);
            if (o == null) {
                return null;
            }
            if (o is JSONArray) {
                return (JSONArray) o;
            }
            return null;
        }

        /**
         *
         * @param key 为空时抛出错误
         * @return 返回取得的值；若key不存在，则返回空值。
         */
        public JSONObject getJSONObject(Object key) {
            Object o = get(key);
            if (o == null) {
                return null;
            }
            if (o is JSONObject) {
                return (JSONObject) o;
            }
            return null;
        }

        /**
         *
         * @param key 为空时抛出错误
         * @return 返回取得的值；若key不存在，则返回空值。
         */
        public Int64 getLong(Object key) {
            Object o = get(key);
            if (o == null) {
                return 0;
            }
            if (o is Int32 || o is Int16 || o is Int64 || o is double) {
                return ((Int64) o);
            }
            return System.Convert.ToInt32(o);
        }

        /**
         *
         * @param key 为空时抛出错误
         * @return 返回取得的值；若key不存在，则返回空值。
         */
        public String getString(Object key) {
            Object o = get(key);
            if (o == null) {
                return null;
            }
            return System.Convert.ToString(o);
        }

        /**
         * @param key 文本型
         * @return 返回JSONPath型的值；若key不存在，则返回空值。
         */
        public JSONPath getPath(Object key) {
            Object o = get(key);
            if (o == null) {
                return null;
            }
            if (o is JSONObject){
                return (JSONPath)o;
            }
            return null;
        }

        /*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/


        private static String numberToString(object n) {
            if (!testValidity(n)) {
                return null;
            }

            // Shave off trailing zeros and decimal point, if possible.
            String s = System.Convert.ToString(n);
            if (s.IndexOf('.') > 0 && s.IndexOf('e') < 0 && s.IndexOf('E') < 0) {
                while (s.EndsWith("0")) {
                    s = s.Substring(0, s.Length - 1);
                }
                if (s.EndsWith(".")) {
                    s = s.Substring(0, s.Length - 1);
                }
            }
            return s;
        }


        /**
         * @param value
         * @param path
         * @return
         * @since
         */
        public static String valueToString(Object value, String path) {
            if (value == null) {
                return "null";
            }
            if (value is String) {
                return quote(System.Convert.ToString(value));
            }
            if (value is cc.hanzs.json.JSONObject) {
                return ((cc.hanzs.json.JSONObject) value).toString(path);
            }
            if (value is cc.hanzs.json.JSONArray) {
                return ((cc.hanzs.json.JSONArray) value).toString(path);
            }
            return System.Convert.ToString(value);
        }


        /**
         *
         * @return 序列化後的文本
         */
        public String toString() {
            clearPath();
            return toString("/");
        }

        public void clearPath() {
            if (path_s == null) {
                return;
            }
            path_s = null;
            foreach (System.Collections.DictionaryEntry objDE in ji集合)
            {
                if (objDE.Value is cc.hanzs.json.JSONObject) {
                    ((cc.hanzs.json.JSONObject) objDE.Value).clearPath();
                }
                if (objDE.Value is cc.hanzs.json.JSONArray) {
                    ((cc.hanzs.json.JSONArray) objDE.Value).clearPath();
                }
            }
        }

        public String toString(String path) {
            if (path_s != null) {
                return path_s;
            }
            path_s = path;
            StringBuilder sb = new StringBuilder();

            foreach (System.Collections.DictionaryEntry objDE in ji集合)
            {
                String value_s;
                if (sb.Length == 0){
                    sb.Append('{');
                } else {
                    sb.Append(',');
                }
                if (path.EndsWith("/")) {
                    value_s = valueToString(objDE.Value, path + objDE.Key);
                } else {
                    value_s = valueToString(objDE.Value, path + "/" + objDE.Key);
                }
                if (value_s != null) {
                    sb.Append(quote((String)objDE.Key));
                    sb.Append(':');
                    sb.Append(value_s);
                }
            }
            if (sb.Length > 0) {
                sb.Append('}');
                return sb.ToString();
            } else {
                return "{}";
            }
        }

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /**
         *
         * 移除自身条目及仔项内的条目，彻底清理佔用资源。用于释放
         */
        public void clear() {
            foreach (System.Collections.DictionaryEntry objDE in ji集合)
            {
                if (objDE.Value is JSONArray) {
                    ((JSONArray) objDE.Value).clear();
                } else if (objDE.Value is JSONObject) {
                    ((JSONObject) objDE.Value).clear();
                }
            }
            ji集合.Clear();
        }

        /**
         *
         * 移除自身的条目，但不移除仔项内的项目，用于清理缓冲
         */
        public void removeall() {
            ji集合.Clear();
        }

        /**
         *
         * @return 新的JSON对象，建议用此方式，加快程序运行速度
         */
        public static cc.hanzs.json.JSONObject d副本() {
            cc.hanzs.json.JSONObject jd;
            jd = (cc.hanzs.json.JSONObject)i_JSON.MemberwiseClone();
            jd.ji集合 = new System.Collections.Hashtable();
            return jd;
        }

        public static cc.hanzs.json.JSONObject d副本(String ci_s) {
            cc.hanzs.json.JSONObject jd;
            jd = (cc.hanzs.json.JSONObject)i_JSON.MemberwiseClone();
            jd.ji集合 = new System.Collections.Hashtable();
            if (ci_s != null) {
                try
                {
                    jd.set(JSONTokener.d副本(ci_s));
                    jd.setPath(jd);
                }
                catch (JSONException)
                {
                }
            }
            return jd;
        }

    }
}
